import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
import { Response } from 'express';
import { SYSTEM_MESSAGE } from 'src/common/constant';
import { MongoError, MongoBulkWriteError } from 'mongodb';
import { ExceptionMap, sendExceptionResponse } from 'src/utils';

/**
 * 捕获系统所有mongodb数据库抛出的异常,非mongoose异常
 */
@Catch(MongoError)
export class MongodbExceptionFilter implements ExceptionFilter {
  catch(exception: MongoError, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    let detail = null;
    //如果异常是BulkWriteError，即使用bulkWrite方法或insertMany报错,封装detail信息
    if (exception instanceof MongoBulkWriteError) {
      const writeErrors = exception['result'].getWriteErrors();
      //循环遍历组成详细信息
      detail = writeErrors.map((e) => {
        return {
          index: e.index,
          code: e.code,
          msg: e.errmsg,
        };
      });
    }
    //根据code码，返回不同的http exception
    const code = exception.code;
    switch (code) {
      case 11000:
        //11000 代表有字段的值已在数据库中存在，发生了冲突
        sendExceptionResponse({
          response,
          statusCode: ExceptionMap.Conflict.statusCode, //409
          message: SYSTEM_MESSAGE.DATA_EXIST, //数据已存在
          errorName: ExceptionMap.Conflict.error, //Conflict
          detail: detail, //详情
          exception: exception, //mongoError
        });
        break;
      default:
        //code未明确时，发送500错误,异常error标记出真实的异常名
        sendExceptionResponse({
          response,
          statusCode: ExceptionMap.Internal_Server_Error.statusCode, //500
          message: SYSTEM_MESSAGE.INTERNAL_EXCEPTION, // 内部错误
          errorName: exception.name, //真实的异常名
          detail: exception.message, //null
          exception: exception, //mongoError
        });
        break;
    }
  }
}
